﻿#include "hnet.h"
#include "hlog.h"
#include "hfolder.h"
#include <iostream>
/**
* old version of test
E:\hhfang_projects\libuv-1.x\libuv-1.x
C:\Users\Administrator\source\repos\test_cpp_code_slice
*/

//#include <thread>
//#include <iostream>
#include <stdio.h>
#include <io.h>
///#include <windows.h>
#include "uv.h"

//struct stls
//{
//    int a;
//};
//#include <thread>
//uv_key_t tls_connctor1;
//
//void thread_run(int a) {
//    struct stls* p = new struct stls;
//    p->a = a;
//    uv_key_set(&tls_connctor1, p);
//    while (1) {
//        auto p = (struct stls*)uv_key_get(&tls_connctor1);
//        std::cout << "--------[" << p->a << "]-------\n";
//    }
//}
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include "happ.h"
#include <thread>
#include <string>
#include <vector>
#include <map>
#include <memory>
static int g_stop = 0;
class CConnector :public  std::enable_shared_from_this<CConnector>
{
public:
    CConnector(connection_id cid) :m_id(cid) {}
    ~CConnector() {}

    connection_id m_id;

};
using sp_connector = std::shared_ptr<CConnector>;
class CConnection :public  std::enable_shared_from_this<CConnection>
{

public:
    CConnection(connection_id cid) :m_id(cid) {}
    ~CConnection() {}

    connection_id m_id;
};
using sp_connection = std::shared_ptr<CConnection>;

class CNetMgr
{
public:
    CNetMgr() {}
    ~CNetMgr() {}
    static CNetMgr& instance() {
        static CNetMgr s_net_mgr;
        return s_net_mgr;
    }
    void add_connector(connection_id id) {
        auto sp = std::make_shared<CConnector>(id);
        m_map_connectors[id] = sp;
    }

    void add_connection(connection_id id) {
        auto sp = std::make_shared<CConnection>(id);
        m_map_connections[id] = sp;
    }

    std::map<connection_id, sp_connector> m_map_connectors;
    std::map<connection_id, sp_connection> m_map_connections;
    std::size_t s_send = 0;
    std::size_t s_recv = 0;
};

#define SigNetMgr CNetMgr::instance()
//static connection_id connection_bit_maps[] = {
//    ((connection_id(1)) << 0) ,
//    ((connection_id(1)) << 1) ,
//    ((connection_id(1)) << 2) ,
//    ((connection_id(1)) << 3) ,
//    ((connection_id(1)) << 4) ,
//    ((connection_id(1)) << 5) ,
//    ((connection_id(1)) << 6)};
//
//static void show_bit_maps() {
//    for (int i = 0; i < sizeof(connection_bit_maps) / sizeof(connection_id); i++) {
//        char s[100] = {0};
//        _itoa_s(connection_bit_maps[i], s, 2);   //转换成字符串，进制基数为2
//        printf("%s\n", s);
//    }
//    auto debug = 0;
//    debug++;
//}
//typedef enum
//{
//    POST_CONNECT = 0,
//    POST_TIMER,
//    POST_WRITE,
//    POST_READ,
//    POST_SHUTDOWN,
//    POST_CLOSE,
//    POST_MAX
//} e_post_type;
//
//static connection_id sbit_move = 1;
//static void show_bit_maps(connection_id id) {
//    for (int i = 0; i < POST_MAX/* sizeof(connection_bit_maps) / sizeof(connection_id)*/; i++) {
//        char s[100] = {0};
//        //
//        if (id & (sbit_move << i)) {
//            _itoa_s(id, s, 2);   //转换成字符串，进制基数为2
//            printf("%s [%d]\n", s, i);
//
//        }
//    }
//    auto debug = 0;
//    debug++;
//}
  /*show_bit_maps(3);
    printf("-------------------------\n");
    show_bit_maps(4);
    printf("-------------------------\n");
    show_bit_maps(7);
    printf("-------------------------\n");
    show_bit_maps(10);
    printf("-------------------------\n");
    auto debug = 0;
    debug++;*/
struct s_gm
{
    struct uv_app_s op;
    char gm_buf[1024];
};

typedef enum
{
    E_TO_APP_CMD_GM = 0,
    E_TO_APP_CMD_MAX
}e_to_app_cmd_type;
static const char* app_log_tag1 = "app_log";

static void on_gm_req(struct uv_app_s* ptr);
static void convert_gm_req(const char* input);
static void handle_gm_req(const std::vector<std::string>& vec);
#include "uv-common.h"

static void collect_gm_req() {
    char szCommand[1024] = {0};
    while (!g_stop) {
        if (fgets(szCommand, sizeof(szCommand), stdin) != nullptr) {
            do {
                // 移除末端的\n
               // char szCmd[1000] = {0};
                struct s_gm* pgm = (struct s_gm*)malloc(sizeof(struct s_gm));
                memset(pgm, 0, sizeof(struct s_gm));
                UV_REQ_INIT(&pgm->op, UV_APP);
                //op_con->op.loop = &ploop->loop;
                pgm->op.data = (void*)E_TO_APP_CMD_GM;
                strcpy_s(pgm->gm_buf, szCommand);
                size_t nLen = strnlen_s(pgm->gm_buf, sizeof(pgm->gm_buf));
                if (0 >= nLen) {
                    break;
                }

                if (pgm->gm_buf[nLen - 1] == '\n') {
                    if (nLen == 1) {
                        printf_s("Command> ");
                        break; //去掉單純換行的行為
                    }
                    pgm->gm_buf[nLen - 1] = '\0';
                }
                post_to_app((uv_app_s*)pgm);
            } while (0);
        }
    }
}
/*
typedef enum
{
    OP_CONNECT = 0,
    OP_ACCEPT,
    OP_SEND,
    OP_CLOSE,
    OP_STOP_CONNECTOR,
    OP_STOP_ACCEPTOR,
    OP_STOP_ALL,
    OP_MAX
} e_op_type;
gm command 也就是这几种类型了
参数具体如下
 connection_id add_connector(const char* cid, const char* ip, int port, int b4true6false, int reconnect_gap);
    connection_id add_acceptor(const char* aid, const char* ip, int port, int b4true6false);
    void stop_acceptor(const char* aid);
    void stop_connector(const char* cid);
    void send_data(connection_id cid, const char* pdata, int len);
    void close_connection(connection_id cid);
*/
static void convert_gm_req(const char* input) {
    std::string str_tmp;
    std::vector<std::string> vec_of_strings;
    for (const char* p = input; *p != '\0'; ) {
        if ((*p) != ' ') {
            str_tmp.push_back((*p));
            p++;
        } else {
            vec_of_strings.push_back(str_tmp);
            str_tmp.clear();
            while ((*p) == ' ') {
                p++;
            }
        }
    }
    if (str_tmp.length()) {
        vec_of_strings.push_back(str_tmp);
    }
    handle_gm_req(vec_of_strings);
    return;
}

typedef enum
{
    OP_CONNECT1 = 0,
    OP_ACCEPT1,
    OP_SEND1,
    OP_CLOSE1,
    OP_STOP_CONNECTOR1,
    OP_STOP_ACCEPTOR1,
    OP_STOP_ALL1,
    OP_MAX1
} e_op_type11;

static void on_gm_req(struct uv_app_s* ptr) {
    if (ptr->data == (void*)(E_TO_APP_CMD_GM)) {
        struct s_gm* gm = (struct  s_gm*)(ptr);
        convert_gm_req(gm->gm_buf);
    }
    free(ptr);
}

static void handle_gm_req(const std::vector<std::string>& vec) {
    if (vec.empty()) {
        return;
    }
    // std::stoull
    int cmd_type = 0;
    try {
        cmd_type = std::stoi(vec[0]);
    } catch (...) {
        HLOG_INFO("cmd_type std::stoi exception [%s]\n", vec[0].c_str());
        return;
    }
    switch (cmd_type) {
    case OP_CONNECT1:
    {
        // connection_id add_connector(const char* cid, const char* ip, int port, int b4true6false, int reconnect_gap);
        if (vec.size() != 6) {
            hlog(app_log_tag1, LOG_ERROR, 1, "OP_CONNECT1 parameter not 6[%d]", vec.size());
            return;
        }
        int port = 0;
        int b4true6false = 1;
        int reconnect_gap = 0;
        try {
            port = std::stoi(vec[3]);
        } catch (...) {
            HLOG_INFO("port std::stoi exception [%s]\n", vec[3].c_str());
            return;
        }
        try {
            b4true6false = std::stoi(vec[4]);
        } catch (...) {
            HLOG_INFO("b4true6false std::stoi exception [%s]\n", vec[4].c_str());
            return;
        }
        try {
            reconnect_gap = std::stoi(vec[5]);
        } catch (...) {
            HLOG_INFO("reconnect_gap std::stoi exception [%s]\n", vec[5].c_str());
            return;
        }
        add_connector(vec[1].c_str(), vec[2].c_str(), port, b4true6false, reconnect_gap);

    }break;
    case OP_ACCEPT1:
    {
    }break;
    case OP_SEND1:
    {
        if (vec.size() != 3) {
            hlog(app_log_tag1, LOG_ERROR, 1, "OP_SEND1 parameter not 6[%d]", vec.size());
            return;
        }
        connection_id id = 0;
        try {
            id = std::stoull(vec[1]);
        } catch (...) {
            HLOG_INFO("OP_SEND1 std::stoi exception [%s]\n", vec[0].c_str());
            return;
        }
#define loop_times (100000)
        for (auto i = 0; i < loop_times; i++) {
            send_data(id, vec[2].c_str(), vec[2].length());
        }
        SigNetMgr.s_send += loop_times * vec[2].length();
    }break;
    case OP_CLOSE1:
    {
    }break;
    case OP_STOP_CONNECTOR1:
    {
    }break;
    case OP_STOP_ACCEPTOR1:
    {
    }break;
    case OP_STOP_ALL1:
    {
    }break;
    default:
    break;
    }
}


int main() {
    //log test here
    init_hnet();
    //多线程写测试
    do {
        std::shared_ptr<std::thread> threadd_array[10];
        for (auto global_count = 0; global_count < 10; global_count++) {
            auto debug = 0;
            debug++;
            threadd_array[global_count] = std::make_shared<std::thread>([&, global_count]() {
                auto debug = 0;
                debug++;
                for (auto n = 0; n < 102400; n++) {
                    hlog("hhhhhhh", LOG_INFO, 0, "hello thread id[%d][%d]\n", global_count, n);
                }
            });
        }
        auto debugd = 0;
        debugd++;
        for (auto i = 0; i < 10; i++) {
            threadd_array[i]->join();
        }
        system("pause");
        auto debug = 0;
        debug++;
    } while (0);
    //压力测试
    do {
#define TOTAL_LOG_FILE (30)
#define FILE_PER_THREAD (3)
#define THEAD_NUM (TOTAL_LOG_FILE/FILE_PER_THREAD)
        int global_count = 0;
        std::vector<std::string> vec_array[THEAD_NUM];
        std::shared_ptr<std::thread> threadd_array[THEAD_NUM];
        int index = 0;
        for (auto i = 0; i < TOTAL_LOG_FILE; i++) {
            if (i % FILE_PER_THREAD == 0 && i != 0) {
                index++;
            }
            char buf[100] = {0};
            sprintf_s(buf, sizeof buf, "log--%d--", i);
            vec_array[index].push_back(buf);
        }
        for (global_count = 0; global_count < THEAD_NUM; global_count++) {

            auto debug = 0;
            debug++;
            threadd_array[global_count] = std::make_shared<std::thread>([&, global_count]() {
                auto debug = 0;
                debug++;
                for (const auto& str : vec_array[global_count]) {
                    for (auto n = 0; n < 1000000; n++) {
                        hlog(str.c_str(), LOG_INFO, 1, "hello[%s][%d]\n", str.c_str(), n);
                    }
                }
            });
        }

        auto debugd = 0;
        debugd++;
        for (auto i = 0; i < THEAD_NUM; i++) {
            threadd_array[i]->join();
        }
        system("pause");
        auto debug = 0;
        debug++;
    } while (0);
    /*  do {
          convert_gm_req("1 2    4  33aaa");
      } while (0);*/
    do {
#define EVERY_ACCEPTOR_CONENCTION (2)
        init_app(on_gm_req);
        std::thread gm_thread([]() {
            collect_gm_req();
        });
        for (auto i = 0; i < EVERY_ACCEPTOR_CONENCTION; i++) {
            char ttt[128] = {0};
            sprintf_s(ttt, sizeof ttt, "c%d", i);
            add_connector(ttt, "10.0.18.221", 9999, 1, 2);
        }
        /* for (auto i = 0; i < EVERY_ACCEPTOR_CONENCTION; i++) {
             char ttt[128] = {0};
             sprintf_s(ttt, sizeof ttt, "d%d", i);
             add_connector(ttt, "10.0.18.221", 9998, 1, 5);
         }
         for (auto i = 0; i < EVERY_ACCEPTOR_CONENCTION; i++) {
             char ttt[128] = {0};
             sprintf_s(ttt, sizeof ttt, "e%d", i);
             add_connector(ttt, "10.0.18.221", 9997, 1, 5);
         }*/
        auto debug = 0;
        debug++;
        //system("pause");
        add_acceptor("a1", "0.0.0.0", 9999, 1);
        /* add_acceptor("a2", "0.0.0.0", 9998, 1);
         add_acceptor("a3", "0.0.0.0", 9997, 1);*/

        while (!g_stop) {
            QUEUE qevents;
            QUEUE_INIT(&qevents);
            QUEUE* head = &qevents;
            get_net_event(&head);
            int n = 0;
            QUEUE* p_tmp_item = NULL;
            while (!QUEUE_EMPTY(&qevents)) {
                p_tmp_item = QUEUE_NEXT(&qevents);
                QUEUE_REMOVE(p_tmp_item);
                net_app_base* p_app_base = QUEUE_DATA(p_tmp_item, net_app_base, event_node);
                /*

                     E_NET_APP_ON_CONNECT_SUCCESS = 0,
        E_NET_APP_ON_CONNECT_FAIL,
        E_NET_APP_ON_CONNECTION,
        E_NET_APP_ON_RECEIVE,
        E_NET_APP_ON_CLOSE,
                */
                if (p_app_base->net_app_type == E_NET_APP_ON_CONNECT_SUCCESS) {
                    net_app_on_connect_success* p_on_connect_success = (net_app_on_connect_success*)(p_app_base);
                    SigNetMgr.add_connector(p_on_connect_success->net_object_id);
                    HLOG_INFO("@net_app_on_connect_success connection id [%llu]remoteip[[%s]remote port[%d]localip[[%s]local port[%d]\n",
                              p_on_connect_success->net_object_id, p_on_connect_success->remote_ip, p_on_connect_success->remote_port
                              , p_on_connect_success->local_ip, p_on_connect_success->local_port);

                } else if (p_app_base->net_app_type == E_NET_APP_ON_CONNECTION) {
                    net_app_on_connection* p_on_connection = (net_app_on_connection*)(p_app_base);
                    SigNetMgr.add_connector(p_on_connection->net_object_id);
                    HLOG_INFO("@net_app_on_connection connection id [%llu]remoteip[[%s]remote port[%d]localip[[%s]local port[%d]\n",
                              p_on_connection->net_object_id, p_on_connection->remote_ip, p_on_connection->remote_port
                              , p_on_connection->local_ip, p_on_connection->local_port);

                } else if (p_app_base->net_app_type == E_NET_APP_ON_RECEIVE) {
                    net_app_on_receive* p_on_receive = (net_app_on_receive*)(p_app_base);
                    SigNetMgr.s_recv += p_on_receive->len;

                    HLOG_INFO("@net_app_on_receive connection id [%llu]data[%s]len[%d] total send [%llu]total receive [%llu]\n", p_on_receive->net_object_id,
                              p_on_receive->buf, p_on_receive->len, SigNetMgr.s_send, SigNetMgr.s_recv);

                }
                n++;
                free(p_app_base);
            }
            if (n > 0) {
                HLOG_INFO("---------------one frame command num[%d]----------------\n", n);
            }
            h_run_once();
        }
        system("pause");
        uninit_hnet();
        uninit_app();
        gm_thread.join();
        system("pause");

    } while (0);

    /* uv_key_create(&tls_connctor1);
     do {
         std::thread th1([&]() {
             thread_run(111);
         });
         std::thread th2([&]() {
             thread_run(222);
         });

         th1.join();
         th2.join();

     } while (0);*/

     /*do {
         int a0 = create_dir_recursive("G:\\test_hh__twy\\t4111\\t2222");
         int a1 = create_dir_recursive("G:/hhh__twy\\d111\\d2222");
         int a2 = create_dir_recursive("whoami__twy/hhfang");
         int a3 = create_dir_recursive("../whoami__twy/hhfang");
         int a4 = create_dir_recursive("..\\..\\test__twy_333\\t4111\\t2222");
         int a5 = create_dir_recursive("..\\..\\test__twy_444\\t4111\\t2222");


         auto debug = 0;
         debug++;

     } while (0);
     do {
         remove_dir_recursive("G:\\test_hide");
         auto debug = 0;
         debug++;
     } while (0);*/
     //do {
     //    HANDLE hFind;
     //    WIN32_FIND_DATAA findData;
     //    LARGE_INTEGER size;

     //    hFind = FindFirstFileA("G:\\test2.0\\*", &findData);
     //    if (hFind == INVALID_HANDLE_VALUE) {
     //        printf("Failed to find first file!\n");
     //        return 0;
     //    }
     //    do {
     //        // 忽略"."和".."两个结果 
     //        if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0)
     //            continue;
     //        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)    // 是否是目录 
     //        {
     //            printf("%s\t<dir>\n", findData.cFileName);
     //        } else {
     //            size.LowPart = findData.nFileSizeLow;
     //            size.HighPart = findData.nFileSizeHigh;
     //            printf("file %s\t size %llu \n", findData.cFileName, size.QuadPart);
     //        }
     //    } while (FindNextFileA(hFind, &findData));
     //    FindClose(hFind); 
     //    printf("Done!\n");
     //} while (0); 
    return 0;
}
